#include "JointScene.h"

#include <NxPlaneShapeDesc.h>

JointScene::JointScene()
{
    this->newtonsCradle = NULL;
}

JointScene::~JointScene()
{
    CleanScene();
}

void JointScene::PrepareScene(NxScene *scene)
{
    PhysxLogic::cam = new Camera(NxVec3(25.0f, 5.0f, 4.0f), NxVec3(-0.7f,0.0f,0.0f), (float)glutGet(GLUT_WINDOW_WIDTH)/(float)glutGet(GLUT_WINDOW_HEIGHT));

    //default material
    NxMaterial *defaultMaterial = scene->getMaterialFromIndex(0);
    defaultMaterial->setRestitution(1.0f);
    defaultMaterial->setStaticFriction(0.0f);
    defaultMaterial->setDynamicFriction(0.0f);

    //create groundPlane
    NxPlaneShapeDesc planeDesc;
    NxActorDesc groundActorDesc;
    groundActorDesc.shapes.pushBack(&planeDesc);
    groundActorDesc.userData = this;
    groundActor = scene->createActor(groundActorDesc);

    newtonsCradle = new NewtonsCradle(NxVec3(6.0f, 0.0f, 4.0f), NxVec3(5.0f, 10.0f, 16.0f), scene, 6, 1.0f, 0.0f);

    scene->setTiming(1.0f/480.0f);
}

void JointScene::CleanScene()
{
    if(this->newtonsCradle != NULL)
    {
        delete newtonsCradle;
        newtonsCradle = NULL;
    }
    if(this->groundActor != NULL)
    {
        PhysxLogic::physicsScene->releaseActor(*groundActor);
        groundActor = NULL;
    }
    delete PhysxLogic::cam;
    PhysxLogic::cam = NULL;
}

void JointScene::Update()
{
}

void JointScene::Draw()
{
    if(groundActor)
    {
        float matrix[16];
        groundActor->getGlobalPose().getColumnMajor44(matrix);
        glPushMatrix();
        glColor3f(0.41f, 0.82f, 0.05f);
        Renderer::DrawPlane(10.0f, 5, 5);
        glPopMatrix();
    }
    if(newtonsCradle)
        newtonsCradle->Draw();
}

void JointScene::HandleKeyboardEvent(unsigned char key, int x, int y)
{
    switch(key)
    {
        case '1':		
        case '2':
        case '3':
        case '4':
        case '5':
        case '6':
        case '7':
        case '8':
        case '9':
        {
            NxActor **balls = newtonsCradle->GetBalls();
            int keyNumber = (int)key - '0';
            if(keyNumber <= newtonsCradle->GetNumBalls())
            {
                for(int i = 0; i < keyNumber; ++i)
                {
                    balls[i]->addForce(NxVec3(0.0f, 0.0f, 500.0f), NX_IMPULSE, true);
                }
            }
            break;
        }
        case 'w': //UP
        {
            NxVec3 dir = PhysxLogic::cam->GetDirection();
            dir.normalize();
            PhysxLogic::cam->MoveBy(dir*1.0);
            break;
        }
        case 's': //DOWN
        {
            NxVec3 dir = PhysxLogic::cam->GetDirection();
            dir.normalize();
            PhysxLogic::cam->MoveBy(-dir*1.0);
            break;
        }
        case 'd': //RIGHT
        {
            NxVec3 dir = PhysxLogic::cam->GetSideNormal();
            dir.normalize();
            PhysxLogic::cam->MoveBy(dir*1.0);
            break;
        }
        case 'a': //LEFT
        {
            NxVec3 dir = PhysxLogic::cam->GetSideNormal();
            dir.normalize();
            PhysxLogic::cam->MoveBy(-dir*1.0);
            break;
        }
    }
}

void JointScene::HandleKeyboardSpecialEvent(int key, int x, int y)
{
    switch(key)
    {
        case GLUT_KEY_F2:
        {
            if(PhysxLogic::IsDebugRenderingEnabled())
            {
                PhysxLogic::SetDebugRenderingEnabled(false);
                PhysxLogic::debugRenderer->DeactivateDebugVisualization(NX_VISUALIZE_JOINT_LOCAL_AXES);
                PhysxLogic::debugRenderer->DeactivateDebugVisualization(NX_VISUALIZE_JOINT_LIMITS);
                PhysxLogic::debugRenderer->DeactivateDebugVisualization(NX_VISUALIZE_COLLISION_SHAPES);
                PhysxLogic::debugRenderer->DeactivateDebugVisualization(NX_VISUALIZE_COLLISION_AXES);
            }
            else
            {
                PhysxLogic::SetDebugRenderingEnabled(true);
                PhysxLogic::debugRenderer->ActivateDebugVisualization(NX_VISUALIZE_JOINT_LOCAL_AXES);
                PhysxLogic::debugRenderer->ActivateDebugVisualization(NX_VISUALIZE_JOINT_LIMITS);
                PhysxLogic::debugRenderer->ActivateDebugVisualization(NX_VISUALIZE_COLLISION_SHAPES);
                PhysxLogic::debugRenderer->ActivateDebugVisualization(NX_VISUALIZE_COLLISION_AXES);
            }
            break;
        }
    }
}

void JointScene::HandleMousePressedMovementEvent(int x, int y, int dx, int dy)
{
}

void JointScene::HandleMouseClickEvent(int button, int state, int x, int y)
{
}
